//
// Created by hoyin on 2024/4/13.
//

#ifndef VISUAL_LOCATION_CLOCK_H
#define VISUAL_LOCATION_CLOCK_H
#include <chrono>

namespace cno = std::chrono;
using stdclock = cno::steady_clock;

class Clock {
private:
	stdclock::time_point _startTime;
	stdclock::time_point _prevTime;
	stdclock::time_point _currTime;
	cno::nanoseconds _tickPeriod;

public:
	Clock() {
		resetClock();
		_tickPeriod = cno::nanoseconds(0);
	}

	/**
	 * 返回上次tick/duration与本次tick之间的时间间隔
	 * @tparam T 使用std::chrono::seconds, std::chrono::milliseconds等时间间隔
	 * @return
	 */
	template<class T>
	T tick();

	/**
	 * 检查当前时间是否到达一个tick周期
	 * @return
	 */
	bool checkTick() {
		if (_tickPeriod.count() == 0) return false;
		_currTime = stdclock::now();
		cno::duration period_ns = _currTime - _prevTime;
		if (period_ns >= _tickPeriod) {
			_prevTime = stdclock::time_point(_currTime);
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 设置tick周期
	 * @tparam T 使用std::chrono::seconds, std::chrono::milliseconds等时间间隔
	 * @param tickPeriod
	 */
	template<class T>
	void setTick(T tickPeriod);

	/**
	 * 返回当前与reset之间的时间间隔
	 * @tparam T 使用std::chrono::seconds, std::chrono::milliseconds等时间间隔
	 * @return
	 */
	template<class T>
	T duration();

	/**
	 * 重置时钟
	 */
	inline void resetClock() {
		_startTime = stdclock::now();
		_prevTime = stdclock::time_point(_startTime);
	}

};

template<class T>
void Clock::setTick(T tickPeriod) {
	_tickPeriod = cno::duration_cast<cno::nanoseconds>(tickPeriod);
	resetClock();
}

template<class T>
T Clock::duration() {
	_currTime = stdclock::now();
	T duration = cno::duration_cast<T>(_currTime - _startTime);
	return duration;
}

template<class T>
T Clock::tick() {
	_currTime = stdclock::now();
	T duration = cno::duration_cast<T>(_currTime - _prevTime);
	_prevTime = _currTime;
	return duration;
}

#endif //VISUAL_LOCATION_CLOCK_H
